/*
 * Copyright (C) 2025 The FlorisBoard Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dev.patrickgold.florisboard.ime.nlp.han

import android.content.Context
import dev.patrickgold.florisboard.ime.core.Subtype
import dev.patrickgold.florisboard.ime.editor.EditorContent
import dev.patrickgold.florisboard.ime.editor.EditorRange
import dev.patrickgold.florisboard.ime.nlp.*
import dev.patrickgold.florisboard.lib.devtools.flogDebug
import dev.patrickgold.florisboard.lib.devtools.flogError
import java.io.BufferedReader
import java.io.InputStreamReader

/**
 * 简化版拼音输入法语言提供者
 * Simplified Pinyin input language provider
 */
class HanPinyinLanguageProvider(val context: Context) : SuggestionProvider {
    companion object {
        const val ProviderId = "org.florisboard.nlp.providers.han.pinyin"
    }

    override val providerId = ProviderId
    override val forcesSuggestionOn = true
    
    // 拼音词典：拼音 -> 汉字列表
    private val pinyinDict = mutableMapOf<String, MutableList<PinyinWord>>()
    
    override suspend fun create() {
        flogDebug { "create() - HanPinyinLanguageProvider create()" }
        loadPinyinDictionary()
    }
    
    override suspend fun preload(subtype: Subtype) {
        flogDebug { "preload() - HanPinyinLanguageProvider preload() for ${subtype.primaryLocale}" }
    }
    
    override suspend fun suggest(
        subtype: Subtype,
        content: EditorContent,
        maxCandidateCount: Int,
        allowPossiblyOffensive: Boolean,
        isPrivateSession: Boolean
    ): List<SuggestionCandidate> {
        return try {
            val query = content.composingText.lowercase().trim()
            if (query.isEmpty()) return emptyList()
            
            flogDebug { "suggest() - Query: '$query'" }
            
            // 1. 精确匹配
            val exactMatches = pinyinDict[query]?.take(5) ?: emptyList()
            
            // 2. 前缀匹配（如果没有精确匹配）
            val prefixMatches = if (exactMatches.isEmpty() && query.length >= 1) {
                pinyinDict.entries
                    .filter { it.key.startsWith(query) }
                    .sortedBy { it.key.length }
                    .take(3)
                    .flatMap { it.value.take(2) }
            } else {
                emptyList()
            }
            
            // 合并结果
            val allCandidates = (exactMatches + prefixMatches).take(maxCandidateCount)
            
            flogDebug { "suggest() - Found ${allCandidates.size} candidates" }
            
            return allCandidates.mapIndexed { index, word ->
                WordSuggestionCandidate(
                    text = word.hanzi,
                    secondaryText = word.pinyin,
                    confidence = 1.0 - (index * 0.1),
                    isEligibleForAutoCommit = false,
                    sourceProvider = this
                )
            }
        } catch (e: Throwable) {
            flogError { "suggest() error: ${e.message}" }
            emptyList()
        }
    }
    
    override suspend fun determineLocalComposing(
        subtype: Subtype,
        textBeforeSelection: CharSequence,
        breakIterators: BreakIteratorGroup,
        localLastCommitPosition: Int
    ): EditorRange {
        return try {
            val text = textBeforeSelection.toString()
            if (text.isEmpty()) {
                return EditorRange.Unspecified
            }
            
            var start = text.length
            val safeLastCommitPosition = maxOf(0, localLastCommitPosition)
            
            // 从后往前找到第一个非字母字符
            for (i in text.length - 1 downTo safeLastCommitPosition) {
                val char = text[i]
                if (!char.isLetter()) {
                    start = i + 1
                    break
                }
                if (i == safeLastCommitPosition) {
                    start = i
                    break
                }
            }
            
            val range = EditorRange(start, text.length)
            flogDebug { "determineLocalComposing() - Range: $start-${text.length}, text: '${text.substring(start)}'" }
            range
        } catch (e: Throwable) {
            flogError { "determineLocalComposing() error: ${e.message}" }
            flogError { "  text='$textBeforeSelection', lastCommit=$localLastCommitPosition" }
            EditorRange.Unspecified
        }
    }
    
    private fun loadPinyinDictionary() {
        try {
            val inputStream = context.assets.open("ime/nlp/pinyin_dict.txt")
            BufferedReader(InputStreamReader(inputStream, "UTF-8")).use { reader ->
                var lineCount = 0
                reader.forEachLine { line ->
                    try {
                        if (line.isBlank() || line.startsWith("#")) return@forEachLine
                        
                        val parts = line.trim().split(Regex("\\s+"))
                        if (parts.size >= 2) {
                            val pinyin = parts[0]
                            val hanzi = parts[1]
                            val frequency = parts.getOrNull(2)?.toIntOrNull() ?: 100
                            
                            // 验证拼音只包含字母
                            if (pinyin.all { it.isLetter() }) {
                                val word = PinyinWord(hanzi, pinyin, frequency)
                                pinyinDict.getOrPut(pinyin) { mutableListOf() }.add(word)
                                lineCount++
                            } else {
                                flogError { "Invalid pinyin: $pinyin" }
                            }
                        }
                    } catch (e: Exception) {
                        flogError { "Error parsing line: $line - ${e.message}" }
                    }
                }
                
                // 按频率排序
                pinyinDict.values.forEach { list -> 
                    list.sortByDescending { it.frequency }
                }
                
                flogDebug { "loadPinyinDictionary() - Loaded $lineCount pinyin entries from ${pinyinDict.size} unique pinyin" }
            }
        } catch (e: Exception) {
            flogError { "loadPinyinDictionary() - Failed: ${e.message}" }
        }
    }
    
    override suspend fun notifySuggestionAccepted(subtype: Subtype, candidate: SuggestionCandidate) {
        flogDebug { "notifySuggestionAccepted() - ${candidate.text}" }
    }
    
    override suspend fun notifySuggestionReverted(subtype: Subtype, candidate: SuggestionCandidate) {
        flogDebug { "notifySuggestionReverted() - ${candidate.text}" }
    }
    
    override suspend fun removeSuggestion(subtype: Subtype, candidate: SuggestionCandidate) = false
    
    override suspend fun getListOfWords(subtype: Subtype): List<String> {
        return pinyinDict.values.flatten().map { it.hanzi }
    }
    
    override suspend fun getFrequencyForWord(subtype: Subtype, word: String): Double {
        return pinyinDict.values.flatten()
            .find { it.hanzi == word }?.frequency?.toDouble() ?: 0.0
    }
    
    override suspend fun destroy() {
        pinyinDict.clear()
        flogDebug { "destroy() - HanPinyinLanguageProvider destroyed" }
    }
    
    data class PinyinWord(
        val hanzi: String,      // 汉字
        val pinyin: String,     // 拼音
        val frequency: Int      // 使用频率
    )
}
